<?php
namespace App\Service;

use Hyperf\Elasticsearch\ClientBuilderFactory;
use Psr\Container\ContainerInterface;
use Hyperf\Contract\ConfigInterface;

class EsService

{
    private $container;
    private $config;
    public function __construct(ContainerInterface $container, ConfigInterface $config){
        $this->container = $container;
        $this->config = $config;
    }

    private function getClient(){
        $builder = $this->container->get(ClientBuilderFactory::class)->create();
        $es_cfg = $this->config->get('elasticsearch');

        return $builder->setHosts($es_cfg['hosts'])->build();
    }

    /**
     * 创建/更新文档
     */
    public function create(string $index, string $id, array $document)
    {
        $params = [
            'index' => $index,
            'id'    => $id,
            'body'  => $document,
        ];
        try {
            $res = $this->getClient()->index($params);
        } catch (\Throwable $e) {
            $msg = $e->getMessage();
            return json_decode($msg,true);
        }

        return $res;
    }

    /**
     * 删除文档
     */
    public function delete(string $index, string $id){
        $params = [
            'index' => $index,
            'id'    => $id
        ];
        try {
            $res = $this->getClient()->delete($params);
        } catch (\Throwable $e) {
            $msg = $e->getMessage();
            return json_decode($msg,true);
        }
        return $res;
    }

    /**
     * 部分更新文档
     */
    public function update(string $index, string $id, array $partialDoc): array
    {
        $params = [
            'index' => $index,
            'id'    => $id,
            'body'  => ['doc' => $partialDoc]
        ];

        try {
            return $this->getClient()->update($params);
        } catch (\Throwable $e) {
            $msg = $e->getMessage();
            return json_decode($msg,true);
        }
    }

    /**
     * 获取单个文档
     */
    public function get(string $index, string $id): ?array
    {
        $params = [
            'index' => $index,
            'id'    => $id
        ];

        try {
            $response = $this->getClient()->get($params);
            return $response;
        } catch (\Elasticsearch\Common\Exceptions\Missing404Exception $e) {
            return null;
        } catch (\Throwable $e) {
            $msg = $e->getMessage();
            return json_decode($msg,true);
        }
    }

    /**
     * 条件搜索文档
     * 
     * @param array $query 查询条件DSL
     * @param int $from 分页起始位置
     * @param int $size 每页数量
     * @param array $sort 排序规则
     */
    public function search(
        string $index, 
        array $query = [], 
        int $from = 0, 
        int $size = 10, 
        array $sort = []
    ): array {
        $params = [
            'index' => 'order_index',
            'body' => [
                'query' => [
                    'multi_match' => [
                        'query' => '拼多多',
                        'fields' => ['source']
                    ]
                ],
                'sort' => [
                    'field_to_sort' => [
                        'id' => 'desc'
                    ]
                ],
                'from' => 10,
                'size' => 10
            ]
        ];

        if (!empty($sort)) {
            $params['body']['sort'] = $sort;
        }

        // try {
            $response = $this->getClient()->search($params);
            return $this->formatSearchResult($response);
        // } catch (\Throwable $e) {
        //     $msg = $e->getMessage();
        //     return json_decode($msg,true);
        // }
    }

    /**
     * 格式化搜索结果
     */
    private function formatSearchResult(array $result): array
    {
        $formatted = [
            'total' => $result['hits']['total']['value'] ?? 0,
            'data'  => [],
            'page'  => [
                'current' => ($result['hits']['hits'] ? 1 : 0),
                'size'    => count($result['hits']['hits'])
            ]
        ];

        foreach ($result['hits']['hits'] as $hit) {
            $formatted['data'][] = array_merge(
                ['_id' => $hit['_id']],
                $hit['_source']
            );
        }

        return $formatted;
    }

    /**
     * 批量操作
     */
    public function bulk(array $operations): array
    {
        try {
            return $this->getClient()->bulk(['body' => $operations]);
        } catch (\Throwable $e) {
            $msg = $e->getMessage();
            return json_decode($msg,true);
        }
    }
}